import * as THREE from "three";
import * as $ from "jquery";
import hammer from "hammerjs";
import { OBJECTS, FLAGS } from "./declarations";
import { TOOLS } from "./tools/tools";
import TweenMax from "gsap/TweenMaxBase";
import { CONFIG } from "./config";
import { DRIVE } from "./drive";

import { DeviceOrientationControls } from "../vendor/threejs/controls/DeviceOrientationControls";
import { ExtrudeGeometry2 } from "../vendor/threejs/geometries/ExtrudeGeometry2";
// import { THREE.TubeGeometry } from "three"
// import { ExtrudeGeometry } from "three"

import { Flow } from "../vendor/threejs/modifiers/CurveModifier";

let joystick_press = false;
let distance = 0;
let actors, materials;
let clock = new THREE.Clock();

let angle = 0;
let offset = {
  x: 0,
  y: 0,
};
let speed = 1;
let delta;
let groups;

let curvePath_last = new THREE.Vector3(0, 0, 0); // last point
let curvePath_preview_last = new THREE.Vector3(0, 0, 0); // last point
let curvePath_distance = 0;
let pointer;

let arrowControl;
let device = CONFIG.release == "dev" ? "pc" : CONFIG.device;
let cameraDistance = new THREE.Vector3();
let cameraDistanceOffset = new THREE.Vector3();
let cameraCenter;
let overridekey = false;

// @TODO : move all game logic inside GAME

var INPUT = {
  // 初始化，添加按钮事件等
  init: () => {
    actors = OBJECTS.actors
    groups = OBJECTS.groups
    materials = OBJECTS.materials

    pointer = OBJECTS.actors.pointer
    OBJECTS.currentCamera = OBJECTS.camera

    console.log(pointer)
    console.log(FLAGS)
    // OBJECTS.currentCamera = actors.cam_pointer

    $("#controls").show()

    $("*").on("click", () => {
      //return false
    })

    //$('body').append('<audio id="music" src="'+ music_id +'" loop autoplay />');

    $("#btn_override").on("click", () => {
      INPUT.playSound('bg',true);
      // 开始按钮
      INPUT.override() // 页面初始化
    })

    $("#control_hold_button").on("mousedown touchstart", () => {
      INPUT.draw(true) // 绘图方法启动，详情参考draw方法的备注
    })

    $("#control_hold_button").on("mouseup touchend", () => {
      INPUT.draw(false) // 绘图方法关闭
    })

    $("#reset").on("click", (e) => {
      INPUT.reset()
    })

    $('#goback').on('click',()=>{
      hideGame3D && hideGame3D();
    })

    // drive button
    $("#control_drive_button").on("click", (e) => {
      DRIVE.start() //绘图结束后，点击开始进行游戏
      INPUT.playSound('s1');
    })
    // 加速按钮（游戏界面的drive按钮）点击
    $("#control_drive_button").on("mousedown touchstart", () => {
      DRIVE.accelerate = true // 加速，下面3个tweenMax是加速时出现的线条
      TweenMax.to(materials.dash, 2, { opacity: 1 })
      TweenMax.to(materials.dash2, 2, { opacity: 0.5 })
      TweenMax.to(materials.dash3, 2, { opacity: 1 })
      INPUT.playSound('s2');
    })
    $("#control_drive_button").on("mouseup touchend", () => {
      DRIVE.accelerate = false
      TweenMax.to(materials.dash, 1, { opacity: 0 })
      TweenMax.to(materials.dash2, 1, { opacity: 0 })
      TweenMax.to(materials.dash3, 1, { opacity: 0 })
    })

    // console.log(music_id);
    // var audio = document.createElement('audio');
    // audio.autoplay = true;
    // audio.loop = true;
    // audio.src = music_id;
    // document.body.appendChild(audio)
    // audio.play()

    // $("#control_switch_view").on("click", (e) => {
    //   INPUT.swapCameras()
    // })
  },
  // 点击start按钮的逻辑
  override: () => {
    $("#override").hide()

    if (device == "android") navigator.vibrate(1)

    $("#control_hold").attr("class", "")

    $(document).on("contextmenu", () => {
      return false
    })

    arrowControl = new DeviceOrientationControls(actors.mid)
    OBJECTS.arrowControl = arrowControl
    // controls2 = new DeviceOrientationControls(actors.cam_container)

    if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
      INPUT.getDevicePermission()
    }

    if (/Android/.test(navigator.userAgent)) {
      device = "android"
      CONFIG.device = device
    }

    if (/Windows/.test(navigator.userAgent)) {
      device = "pc"
    }

    if (device == "android") arrowControl.alphaOffset = TOOLS.d2r(-90)

    INPUT.initDrawLine()

    window.addEventListener("devicemotion", INPUT.onDeviceMotion, true)
    window.addEventListener("deviceorientation", INPUT.onDeviceOrientation)
  },

  /**
   * 这部分的逻辑是这样的：
   * draw入参为true的时候，开始绘制地图
   * 绘制地图的方法由render.js里的requestAnimationFrame方法调用，本js文件最下方的tick()方法内触发，FLAGS.hold为true时开始绘图，参考下方tick()方法
   *
   * @param {*} val
   */
  draw: (val) => {
    if (val == true) {
      $("#control_hold_button").attr("class", "hold")
      FLAGS.hold = true
      INPUT.swapCameras(actors.cam_pointer)
    } else {
      $("#control_hold_button").attr("class", "")
      FLAGS.hold = false
      // 这里判断绘制的赛道的路径点的长度达到开始比赛的长度，就出现drive按钮，具体配置参考declarations.js里的curvepath_step和curvepath_readydrive参数
      if (OBJECTS.curvepath_points.length > FLAGS.curvepath_readydrive) {
        $("#control_hold_button").attr("class", "hide")
        $("#control_drive_button").attr("class", "")
      }else{ 
        let tpro = parseFloat((FLAGS.curvepath_readydrive/OBJECTS.curvepath_points.length*100).toFixed(2));

        $("#control_hold_button .before").css(
          "background",
          "conic-gradient(#FFCDB2 0, #FFCDB2 " +
            tpro +
            "%, #ff5722 " +
            (tpro + 0.01) +
            "%, #ff5722 100%)"
        )
      }

      INPUT.drawDrivePath()
      window.setTimeout(() => {
        INPUT.swapCameras(OBJECTS.camera)
        setTimeout(() => {
          INPUT.cutImage()
        }, 1000)
        console.log("此处截图")
      }, 100)
    }
  },

  playSound(type,loop=false) {
    let url = '';
    if(type=='bg'){
      if(null==localStorage.getItem('musicUrl')){
        url = './music/Easygoing.mp3';
      }else{
        url = localStorage.getItem('musicUrl');
      }
    }else{
      const URLS = { 
        s1: './music/start.mp3',
        s2: './music/fast.mp3',
      }
      url = URLS[type];
    }
    
    const listener = new THREE.AudioListener();
    OBJECTS.camera.add(listener);
    const sound = new THREE.Audio(listener);
    const audioLoader = new THREE.AudioLoader();
    audioLoader.load(url, function (buffer) {
      sound.setBuffer(buffer);
      sound.setLoop(loop);
      sound.setVolume(0.5);
      sound.play();
    });

  },

  cutImage: () => {
    var simg = new Image()
    simg.onload = () => {
      console.log(simg)
      var can = document.createElement("canvas")
      let innerHeight = simg.height
      let innerWidth = simg.width
      can.width = innerWidth * 0.8
      can.height = innerWidth * 0.8
      var ctx = can.getContext("2d") 
      ctx.drawImage(
        simg,
        innerWidth * 0.1,
        (innerHeight - innerWidth) / 2,
        innerWidth * 0.8 ,
        innerWidth * 0.8 ,
        0,
        0,
        can.width,
        can.height
      )
      var img = can.toDataURL("image/png")
      
      /*
        $('#imgview').css('background-image','url('+ img +')');
        $('#imgviewBox').show(); 
      */
      window.localStorage.setItem("ROAD_IMG", img)
    }
    simg.src = renderer.domElement.toDataURL()
  },

  reset: () => {
    // location.reload() // debug

    // Reset the button states
    $("#control_hold_button").attr("class", "")
    $("#control_drive_button").attr("class", "hide")

    // Reset the drive points array,
    // initial values with z offset to prevent weird twisting when
    // adjoining curve points are too close
    OBJECTS.curvepath_drive_points = [new THREE.Vector3(0, 0, -10)]
    OBJECTS.curvepath_preview_points = [new THREE.Vector3(0, 0, -10)]

    // Resets the pointer position, visibility and the render camera
    actors.pointer.position.set(0, 0, 0)
    actors.arrow.visible = true
    OBJECTS.currentCamera = OBJECTS.camera

    // Removes any existing curve meshes for drive and preview
    if (OBJECTS.curvemesh_preview)
      groups.preview.remove(OBJECTS.curvemesh_preview)
    if (OBJECTS.curvemesh_preview)
      groups.drive.remove(OBJECTS.curvemesh_drive)

    // Re initialize
    INPUT.initDrawLine()

  },

  swapCameras: (cam) => {
    if (cam) {
      OBJECTS.currentCamera = cam
    } else {
      OBJECTS.currentCamera =
        OBJECTS.currentCamera == OBJECTS.camera
          ? actors.cam_pointer
          : OBJECTS.camera
    }

    if (OBJECTS.currentCamera == OBJECTS.camera) {
      // move the camera target to the center of the drawn road path / OBJECTS.curveObject

      if (OBJECTS.curveobject_drive) {
        // const c = OBJECTS.curveobject.geometry.boundingSphere.center.copy()
        cameraCenter = OBJECTS.curveobject_drive.geometry.boundingSphere.center
        cameraDistance =
          OBJECTS.curveobject_drive.geometry.boundingSphere.radius * 4

        OBJECTS.cam_target = cameraCenter
        OBJECTS.camera.position.z = cameraDistance
      }
    }
  },

  onDeviceOrientation: (event) => {
    // TOOLS.adaptWindow(OBJECTS.currentCamera)
    // deprecated, using modified DeviceOrientationControls
    // alert('lel')
    // let out = ""
    // out += "alpha : " + event.alpha + "</br/>"
    // out += "beta : " + event.beta + "</br/>"
    // out += "gamma : " + event.gamma + "</br/>"
    // $("#debug").html(out)
    // return false;
  },
  // pc测试时触发的绘制函数，无法转弯。下方onDeviceMotion方法是手机陀螺仪触发的方法，现状是必须手动起来才能绘制赛道。
  _debugMoveForward: () => {
    // console.log('raf')
    let out = ""
    let mult = CONFIG.input.accelerometerSpeed

    const acceleration = new THREE.Vector3(0, 0, 1)
    const velocityZ = acceleration.z * mult

    OBJECTS.input.velocity = Math.abs(acceleration.z)

    const innerRotation = new THREE.Euler()
    actors.arrow.getWorldQuaternion(innerRotation)

    const forwardVector = new THREE.Vector3(0, 1, 0) // Assuming forward is in the negative z-axis direction
    forwardVector.applyEuler(innerRotation)

    if (Math.abs(acceleration.z) > 0.1 && FLAGS.hold) {
      actors.pointer.translateOnAxis(forwardVector, Math.abs(velocityZ))
    }
    // 核心绘制赛道函数
    INPUT.checkLinePointDistance_Drive()

    out = `VelZ: ${acceleration.z}`
  },
  // 陀螺仪触发
  onDeviceMotion: (event) => {
    if(!window.tmr)window.tmr=0;
    window.tmr++;
    if(window.tmr<10){
      //return false;
    }else{
      window.tmr = 0;
    }
    console.log("陀螺仪触发")
    // console.log('raf')
    let out = ""
    let mult = CONFIG.input.accelerometerSpeed

    const acceleration = event.acceleration
    const velocityZ = acceleration.z * mult

    OBJECTS.input.velocity = Math.abs(acceleration.z)

    const innerRotation = new THREE.Euler()
    actors.arrow.getWorldQuaternion(innerRotation)

    const forwardVector = new THREE.Vector3(0, 1, 0) // Assuming forward is in the negative z-axis direction
    forwardVector.applyEuler(innerRotation)

    if (Math.abs(acceleration.z) > 0.1 && FLAGS.hold) {
      actors.pointer.translateOnAxis(forwardVector, Math.abs(velocityZ))
    }

    INPUT.checkLinePointDistance_Drive()

    out = `VelZ: ${acceleration.z}`

    //
    // const accelerationInclGravity = event.accelerationIncludingGravity;
    // DRIVE.steer(acceleration.x * mult);
    // if(DRIVE.ready == true){
    //   const velocityX = accelerationIncludingGravity.x * driveSteerMultiplier;
    //   // $("#debug").html(">>> " + velocityX)
    //   DRIVE.steer(velocityX)

    // }

    // if(DRIVE.ready){
    //   const velocityX = acceleration.x * FLAGS.driveSteerMultiplier;
    //   $("#debug").html(velocityX)
    // }
  },

  getDevicePermission: () => {
    //if(device == 'pc') return;
    DeviceOrientationEvent.requestPermission()
      .then((response) => {
        if (response == "granted") {
          window.addEventListener("deviceorientation", (event) => {
            if(!window.tmr)window.tmr=0;
            window.tmr++;
            if(window.tmr<10){
              //return false;
            }else{
              window.tmr = 0;
            }
            let out = ""
            let { alpha, beta, gamma } = event
            // do something with e
            let mult = CONFIG.input.accelerometerSpeed

            const velocityZ = gamma * mult

            OBJECTS.input.velocity = Math.abs(gamma)

            const innerRotation = new THREE.Euler()
            actors.arrow.getWorldQuaternion(innerRotation)

            const forwardVector = new THREE.Vector3(0, 1, 0) // Assuming forward is in the negative z-axis direction
            forwardVector.applyEuler(innerRotation)

            if (Math.abs(gamma) > 0.1 && FLAGS.hold) {
              actors.pointer.translateOnAxis(forwardVector, Math.abs(velocityZ))
            }

            INPUT.checkLinePointDistance_Drive()

            out = `VelZ: ${gamma}`
          })
        }
      })

      .catch(console.error)
  },

  initDrawLine: () => {
    OBJECTS.curveobject_drive = new THREE.Object3D()
    groups.trails.add(OBJECTS.curveobject_drive)
    console.log("initDrawLine")
    let sp1 = OBJECTS.sps[0]
    let sp2 = OBJECTS.sps[1]
    let sp3 = OBJECTS.sps[2]

    OBJECTS.curvepath_extra = [
      {
        ref: sp1,
        path: [new THREE.Vector3().copy(sp1.position)],
        curveobject: new THREE.Object3D(),
      },
      {
        ref: sp2,
        path: [new THREE.Vector3().copy(sp2.position)],
        curveobject: new THREE.Object3D(),
      },
      {
        ref: sp3,
        path: [new THREE.Vector3().copy(sp3.position)],
        curveobject: new THREE.Object3D(),
      },
    ]

    groups.trails.add(OBJECTS.curvepath_extra[0].curveobject)
    groups.trails.add(OBJECTS.curvepath_extra[1].curveobject)
    groups.trails.add(OBJECTS.curvepath_extra[2].curveobject)

    actors.pointer.position.set(0, 0, 0)
    OBJECTS.currentCamera = actors.cam_pointer
    actors.cam_container.rotation.copy(new THREE.Euler(0, 0, 0))
  },
  // 似乎暂时未用到
  drawLine: (point, velo) => {
    if (OBJECTS.curveobject_drive)
      groups.trails.remove(OBJECTS.curveobject_drive)

    OBJECTS.curvepath_points.push(point)
    OBJECTS.curvepath_velocity.push(OBJECTS.input.velocity)

    let path = new THREE.CatmullRomCurve3(OBJECTS.curvepath_points)
    path.curveType = "chordal"
    path.tension = 0

    // let points = path.getPoints(OBJECTS.curvepath_points.length * 10)

    let geometry = new THREE.TubeGeometry(
      path,
      OBJECTS.curvepath_points.length * 3,
      1,
      2,
      false
    )
    let material = new THREE.MeshNormalMaterial({
      wireframe: false,
      side: THREE.BackSide,
    })
    let curveobject = new THREE.Mesh(geometry, materials.normal)

    OBJECTS.curveobject_drive = curveobject
    groups.trails.add(OBJECTS.curveobject_drive)

    // INPUT.drawExtraLines()
  },
  // 没用
  drawFollowPath: (final = false) => {
    if (OBJECTS.curvepath_follow) groups.root.remove(OBJECTS.curvepath_follow)

    let path = new THREE.CatmullRomCurve3(OBJECTS.curvepath_points)
    path.curveType = "chordal"
    path.tension = 0
    path.closed = false

    const geometry = new THREE.TubeGeometry(path, path.length, 0.8, 2, final)

    const mesh = new THREE.Mesh(geometry, materials.normal)
    // materials.normal.wireframe = true
    // mesh.visible = false

    groups.root.add(mesh)
    OBJECTS.curvepath_follow = mesh
  },
  // 没用
  drawPreviewRoad: (point, velo) => {
    // OBJECTS.curvepath_preview_points.push(point);
    // OBJECTS.curvepath_preview_velocity.push(OBJECTS.input.velocity);
  },

  // this method draws the preview road 逐帧绘制地面
  drawRoad: (point, velo) => {
    if (OBJECTS.curveobject_drive)
      groups.trails.remove(OBJECTS.curveobject_drive)

    OBJECTS.curvepath_points.push(point)
    OBJECTS.curvepath_velocity.push(OBJECTS.input.velocity)

    // 根据路径点绘制曲线
    let path = new THREE.CatmullRomCurve3(OBJECTS.curvepath_points)
    path.curveType = "chordal"
    path.tension = 0
    path.closed = false
    // -2.4为轮胎半径，这里是生成一个新的路面切片，-2和2是切片的宽度，-2.4为切片的位置向下移动了2.4，这个位置与轮胎目前的半径一致，这样绘制的路面就在轮胎下方了
    let points = [new THREE.Vector2(-2, -2.4), new THREE.Vector2(2, -2.4)]

    let shape = new THREE.Shape(points)

    let geometry = new ExtrudeGeometry2(shape, {
      steps: OBJECTS.curvepath_points.length * 1,
      bevelEnabled: false,
      extrudePath: path,
      weights: OBJECTS.curvepath_velocity,
    })

    let curveobject = new THREE.Mesh(geometry, materials.trail_draw)

    TOOLS.resetUV(curveobject)

    OBJECTS.curveobject_drive = curveobject
    groups.trails.add(OBJECTS.curveobject_drive)

    // INPUT.drawFollowPath()
    // INPUT.drawExtraLines()
  },

  uvGenerator: {
    generateTopUV: function (geometry, vertices, idxA, idxB, idxC) {
      var ax, ay, bx, by, cx, cy

      ax = vertices[idxA * 3]
      ay = vertices[idxA * 3 + 1]
      bx = vertices[idxB * 3]
      by = vertices[idxB * 3 + 1]
      cx = vertices[idxC * 3]
      cy = vertices[idxC * 3 + 1]
      return [
        new THREE.Vector2(ax, ay),
        new THREE.Vector2(bx, by),
        new THREE.Vector2(cx, cy),
      ]
    },
    generateSideWallUV: function (geometry, vertices, idxA, idxB, idxC, idxD) {
      return [
        new THREE.Vector2(0, 0),
        new THREE.Vector2(1, 0),
        new THREE.Vector2(1, 1),
        new THREE.Vector2(0, 1),
      ]
    },
  },
  // 没用
  drawExtraLines: () => {
    let spawnpoints = OBJECTS.curvepath_extra

    spawnpoints.forEach((element) => {
      if (element.curveobject) groups.trails.remove(element.curveobject)

      const point = element.ref.getWorldPosition(new THREE.Vector3())
      element.path.push(point)

      const path = new THREE.CatmullRomCurve3(element.path)
      path.curveType = "chordal"
      path.tension = 0

      const geometry = new THREE.TubeGeometry(
        path,
        element.path.length,
        0.2,
        2,
        false
      )

      const mesh = new THREE.Mesh(geometry, materials.trail_draw)

      element.curveobject = mesh

      groups.trails.add(mesh)
    })
  },
  // 没用
  drawFinalRoadPathExtra: () => {
    let spawnpoints = OBJECTS.curvepath_extra

    spawnpoints.forEach((element) => {
      if (element.curveobject) groups.trails.remove(element.curveobject)

      const point = element.ref.getWorldPosition(new THREE.Vector3())
      element.path.push(point)

      const path = new THREE.CatmullRomCurve3(element.path)
      path.curveType = "chordal"
      path.tension = 0
      path.closed = true

      const geometry = new THREE.TubeGeometry(
        path,
        element.path.length * 3,
        0.1,
        3,
        false
      )

      const mesh = new THREE.Mesh(geometry, materials.trail_draw)
      mesh.castShadow = true

      element.curveobject = mesh
      groups.trails.add(mesh)
    })
  },

  // draw the final road path to drive on using Curves and Tube Geometry for proper UV mapping
  // 这段是绘图最终的赛道，取消了绘制赛道，依然会绘制返回部分
  drawDrivePath: () => {
    if (OBJECTS.curveobject_drive)
      groups.trails.remove(OBJECTS.curveobject_drive)

    let path = new THREE.CatmullRomCurve3(
      OBJECTS.curvepath_points,
      true,
      "chordal",
      1
    )
    OBJECTS.curvepath = path
    console.log(OBJECTS.curvepath_points.length)
    // main_road_geo是赛道
    const main_road_geo = new THREE.TubeGeometry(
      path,
      OBJECTS.curvepath_points.length * 16,
      1,
      2,
      true
    )

    let main_road_mesh = new THREE.Mesh(main_road_geo, materials.trail_draw)
    main_road_mesh.position.set(0, 0, 0)

    main_road_mesh.receiveShadow = true
    main_road_mesh.castShadow = true
    // 下面3个dash都是加速时出现的长条
    const dash_geo = new THREE.TubeGeometry(
      path,
      OBJECTS.curvepath_points.length * 8,
      2,
      6,
      true
    )

    const dash_geo2 = new THREE.TubeGeometry(
      path,
      OBJECTS.curvepath_points.length * 8,
      3,
      6,
      true
    )

    const dash_geo3 = new THREE.TubeGeometry(
      path,
      OBJECTS.curvepath_points.length * 8,
      1,
      3,
      true
    )

    let dash_mesh = new THREE.Mesh(dash_geo, materials.dash)
    let dash_mesh2 = new THREE.Mesh(dash_geo2, materials.dash2)
    let dash_mesh3 = new THREE.Mesh(dash_geo3, materials.dash3)

    if (window.dash_mesh) {
      groups.trails.add(window.dash_mesh)
    }
    if (window.dash_mesh2) {
      groups.trails.add(window.dash_mesh2)
    }
    if (window.dash_mesh3) {
      groups.trails.add(window.dash_mesh3)
    }

    window.dash_mesh = dash_mesh
    window.dash_mesh2 = dash_mesh2
    window.dash_mesh3 = dash_mesh3
    // main_road_geo.position.set(0,-2,0);
    //dash_mesh.position.z +=1;
    // let lines_mesh = new THREE.Mesh(lines_geo, materials.normalwire);
    // alert(1);
    OBJECTS.curveobject_drive = main_road_mesh
    groups.trails.add(OBJECTS.curveobject_drive)
    groups.trails.add(dash_mesh)
    groups.trails.add(dash_mesh2)
    groups.trails.add(dash_mesh3)

    OBJECTS.curveobject_drive.visible = true
    // alert(0);
    // let curveobject = new THREE.Mesh(geometry, materials.trail_draw);
  },

  checkLinePointDistance_Preview: () => {
    // if (distance > FLAGS.curvepath_preview_step) {
    //   curvePath_preview_last.copy(pointer.position);
    //   const offset = new THREE.Vector3().copy(pointer.position);
    //   // offset.y -= 1
    //   // const pos = new THREE.Vector3().copy(pointer.position)
    //   const pos = offset;
    //   INPUT.drawRoad(pos);
    // }
  },

  checkLinePointDistance_Preview: () => {
    // WIP

    let distance = curvePath_last.distanceTo(pointer.position)
    if (distance > FLAGS.curvepath_step) {
      curvePath_last.copy(pointer.position)

      const offset = new THREE.Vector3().copy(pointer.position)
      const lastPoint =
        OBJECTS.curvepath_points[OBJECTS.curvepath_points.length - 1]
      if (lastPoint.x - offset.x > 0) {
        offset.x = lastPoint.x - Math.max(lastPoint.x - offset.x, 0.01)
      } else if (lastPoint.x - offset.x < 0) {
        offset.x = lastPoint.x + Math.max(offset.x - lastPoint.x, 0.01)
      }
      const pos = offset
      INPUT.drawRoad(pos)
    }

    distance = TOOLS.roundOffDecimal(distance)

    out += `distance from last point: ${distance}<br/>`
    out += `pointer: <br/>   x ${TOOLS.roundOffDecimal(
      pointer.position.x
    )} <br/>y${TOOLS.roundOffDecimal(
      pointer.position.y
    )}<br/> z ${TOOLS.roundOffDecimal(pointer.position.z)}`

    // out += `deltatime: ${OBJECTS.delta}`
    out += `<br/>velocity: ${OBJECTS.input.velocity}`
  },

  // 点击开始后逐帧绘制
  checkLinePointDistance_Drive: () => {
    // console.log('requestAnimationFrame')
    let out = ""

    let distance = curvePath_last.distanceTo(pointer.position)
    // console.log(distance);
    // curvepath_step 这个参数是步长，越小绘制越精确
    // console.log(distance);
    if (distance > FLAGS.curvepath_step) {
      curvePath_last.copy(pointer.position)

      const offset = new THREE.Vector3().copy(pointer.position)
      // offset.y -= 1
      // 下面这部分逻辑是让转弯角度不能过大
      const lastPoint =
        OBJECTS.curvepath_points[OBJECTS.curvepath_points.length - 1]
      if (lastPoint.x - offset.x > 0) {
        offset.x = lastPoint.x - Math.max(lastPoint.x - offset.x, 0.01)
      } else if (lastPoint.x - offset.x < 0) {
        offset.x = lastPoint.x + Math.max(offset.x - lastPoint.x, 0.01)
      }
      // console.log(offset);
      // const pos = new THREE.Vector3().copy(pointer.position)
      const pos = offset
      // pointer.rotation.set(INPUT.getPointerRotation());
      // 绘图函数
      INPUT.drawRoad(pos)
    }

    distance = TOOLS.roundOffDecimal(distance)

    out += `distance from last point: ${distance}<br/>`
    out += `pointer: <br/>   x ${TOOLS.roundOffDecimal(
      pointer.position.x
    )} <br/>y${TOOLS.roundOffDecimal(
      pointer.position.y
    )}<br/> z ${TOOLS.roundOffDecimal(pointer.position.z)}`

    // out += `deltatime: ${OBJECTS.delta}`
    out += `<br/>velocity: ${OBJECTS.input.velocity}`

    // $("#debug").html(out)
  },

  getPointerRotation: () => {
    const rotation1 = TOOLS.getQuaternionFromObject(actors.low)
    const rotation2 = TOOLS.getQuaternionFromObject(actors.mid)

    const combinedQuaternion = new THREE.Quaternion()
    combinedQuaternion.multiplyQuaternions(rotation1, rotation2)

    const combinedRotation = TOOLS.combineQuaternions(rotation1, rotation2)

    return combinedRotation
  },
  // 镜头跟随轮子前进
  followPointer: () => {
    actors.cam_pointer.lookAt(actors.pointer.position)
    // console.log(OBJECTS.delta);

    const lerpedPosition = new THREE.Vector3().lerpVectors(
      actors.cam_container.position,
      actors.pointer.position,
      OBJECTS.delta * 0.5
    )

    actors.cam_container.position.copy(lerpedPosition)
  },

  tick: () => {

    INPUT.followPointer() // 镜头跟随轮子前进

    // console.log(OBJECTS.orientation)

    if (device == "pc") INPUT._debugMoveForward()

    if (!FLAGS.hold) {
      // rotate the main camera
      if (!CONFIG.camera.controls.enabled)
        groups.followCam.rotation.y += 0.08 * OBJECTS.delta
    }

    if (arrowControl) {
      arrowControl.update()

      let q = new THREE.Quaternion()

      actors.cam_pointer.rotation.z = actors.mid.rotation.z
      actors.cam_container.rotation.x = actors.mid.rotation.x

      // damp3(actors.cam_pointer.rotation, actors.mid.rotation, 0.25, OBJECTS.delta)
    }
  },
}

export { INPUT };
